/*
 * tw2855.c
 *
 *  Created on: 2021-2-7
 *      Author: Administrator
 */
/********************************************************** TW2825_OPEN() ***/
#include "i2c_ops.h"
#include "board.h"
#include "tp2855.h"
#ifndef TRACE
	#define TRACE
#endif
extern void
logmsg( const char *fmt, ... );

int
tw2855_open(tw2855_context_t *ctx)
{
	TRACE;
	int error = 0;
	uint32_t bus_speed_hz = 400000;
	uint8_t chip_id_h = 0;
	uint8_t chip_id_l = 0;

	if(strlen(ctx->dev_path) == 0) {
		logmsg("%s: device path is not set.\n", __FUNCTION__);
		return ENODEV;
	}

	if(ctx->dev_addr == 0) {
		logmsg("%s: device address is not set.\n", __FUNCTION__);
		return ENODEV;
	}
	if((ctx->device_fd = open(ctx->dev_path, O_RDWR)) == -1) {
		logmsg( "%s:failed open i2c device %s (%s).\n", __FUNCTION__, ctx->dev_path, strerror(errno));
		return errno;
	}

	if((error = devctl(ctx->device_fd, DCMD_I2C_SET_BUS_SPEED,
			&bus_speed_hz, sizeof bus_speed_hz, NULL)) != EOK) {
		logmsg("%s: failed to set i2c bus speed (%s).\n", __FUNCTION__, strerror(error));
		return error;
	}
	//set common register access
	if(EOK != (i2c_wr(ctx->device_fd, ctx->dev_addr,TW2825_GEN_CTRL,0x00))){
		logmsg("%s: failed to get chip general control(%s).\n", __FUNCTION__, strerror(error));
		return ENODEV;
	}
	// read device identifier
	error |= i2c_rd(ctx->device_fd, ctx->dev_addr, TW2855_ID_HIGH, &chip_id_h);
	error |= i2c_rd(ctx->device_fd, ctx->dev_addr, TW2855_ID_LOW, &chip_id_l);
	if((error != EOK) || (chip_id_h != 0x28) || (chip_id_l != 0x55)){
		logmsg("%s: failed to get chip identifier(%s).\n", __FUNCTION__, strerror(error));
		return ENODEV;
	}

	return EOK;
}
int tp28xx_write_reg(tw2855_context_t *ctx,uint8_t reg_addr,uint8_t reg_value){
	if(ctx->device_fd <= 0){
		logmsg("%s: i2c device fd has not initialized.\n", __FUNCTION__);
		return(-1);
	}
	if(ctx->dev_addr <= 0){
		logmsg("%s: i2c device slave address has not initialized.\n", __FUNCTION__);
		return(-1);
	}
	if(EOK != i2c_wr(ctx->device_fd, ctx->dev_addr, reg_addr, reg_value)){
		return(-1);
	}
	return 0;
}
uint8_t tp28xx_read_reg(tw2855_context_t *ctx,uint8_t reg_addr){
	uint8_t reg_value = 0;
	if(ctx->device_fd <= 0){
		logmsg("%s: i2c device fd has not initialized.\n", __FUNCTION__);
		return(-1);
	}
	if(ctx->dev_addr <= 0){
		logmsg("%s: i2c device slave address has not initialized.\n", __FUNCTION__);
		return(-1);
	}
	if(EOK != i2c_rd(ctx->device_fd, ctx->dev_addr, reg_addr, &reg_value)){
		return(-1);
	}
	return reg_value;
}
int tw_2855_dump(tw2855_context_t* ctx){
	if(ctx->device_fd <= 0){
		logmsg("%s: i2c device has not initialized.\n", __FUNCTION__);
		return(-1);
	}
	if(ctx->dev_addr <= 0){
		logmsg("%s: i2c device slave address has not initialized.\n", __FUNCTION__);
		return(-1);
	}
	printf(" Dump Tp2855 channel[%d]:\n",CH_1);
	tp28xx_write_reg(ctx,0x40,CH_1);
	i2c_dumper(ctx->device_fd, ctx->dev_addr, 0x00 , 0xFF);
	printf(" Dump Tp2855 channel[%d]:\n",CH_2);
	tp28xx_write_reg(ctx,0x40,CH_2);
	i2c_dumper(ctx->device_fd, ctx->dev_addr, 0x00 , 0xFF);
	printf(" Dump Tp2855 channel[%d]:\n",CH_3);
	tp28xx_write_reg(ctx,0x40,CH_3);
	i2c_dumper(ctx->device_fd, ctx->dev_addr, 0x00 , 0xFF);
	printf(" Dump Tp2855 channel[%d]:\n",CH_4);
	tp28xx_write_reg(ctx,0x40,CH_4);
	i2c_dumper(ctx->device_fd, ctx->dev_addr, 0x00 , 0xFF);
	printf(" Dump Tp2855 channel[%d]:\n",MIPI_PAGE);
	tp28xx_write_reg(ctx,0x40,MIPI_PAGE);
	i2c_dumper(ctx->device_fd, ctx->dev_addr, 0x00 , 0xFF);

	return 0;
}
int is_tp2855_video_available(tw2855_context_t* ctx,uint8_t channel){
#define MAX_CAM_CONN_RETRY 10
	int _retry = MAX_CAM_CONN_RETRY;
	uint8_t vin_status = 0;
	if(ctx->device_fd <= 0){
		logmsg("%s: i2c device has not initialized.\n", __FUNCTION__);
		return(-EINVAL);
	}
	if(ctx->dev_addr <= 0){
		logmsg("%s: i2c device slave address has not initialized.\n", __FUNCTION__);
		return(-EINVAL);
	}
	tp28xx_write_reg(ctx,0x40, channel);
	for(;_retry>0;_retry--){
		if(EOK != i2c_rd(ctx->device_fd, ctx->dev_addr,
				TW2855_VIN_STATUS, &vin_status)){
			logmsg("%s: i2c device unaccessable.\n", __FUNCTION__);
			delay(100);
			continue;
		}
//		if(((vin_status & 0x71) != 0x70)
//		&&((vin_status & 0x71) != 0x61)){
//			delay(100);
//			continue;
//		}
//		break;
		if((vin_status >> 7)== 0)
			break;
		delay(100);
		continue;
	}
	if(_retry <= 0){
		logmsg("check channel[%d] lock NG 0x%02x\n", channel, vin_status);
		return(0);
	}
	return 1;
}

int IMX6S_ROT270_FLAG = 0;
int is_tp2855_connect_status(){
#define DECODER_ADDR		0x44
#define TP2855_REG_PAGE		0x40
#define TP2855_REG_VIDEO_INPUT_STATUS	0x01
	int fd = -1;static int time_out = 0;

	uint8_t lock = 0;
	int i, status = 0;

	fd = open("/dev/i2c1", O_RDWR);
	if(fd == -1)
		logmsg("[is_tp2855_connect_status] open i2c1 failed.\n");

	for (i = 0; i < 4; i++) {
		time_out = 0;
		while(time_out < 5){
			if (i2c_wr(fd, DECODER_ADDR, TP2855_REG_PAGE, i) != 0) {
					logmsg("[is_tp2855_connect_status] fail to write device page %d(%s)\n", errno, strerror(errno));
					goto error;
				}

				if (i2c_rd(fd, DECODER_ADDR, TP2855_REG_PAGE, &lock) != 0) {
					logmsg("[is_tp2855_connect_status] fail to read device lock status %d(%s)\n", errno, strerror(errno));
					goto error;
				}
				delay(time_out*10);
				if(lock != i){
					logmsg("[is_tp2855_connect_status] change page fail, timout is %d %d(%s)\n", time_out, errno, strerror(errno));
				}
				else{
					break;
				}
				time_out++;
		}
		if (i2c_rd(fd, DECODER_ADDR, TP2855_REG_VIDEO_INPUT_STATUS, &lock) != 0) {
			logmsg("[is_tp2855_connect_status] fail to read device lock status %d(%s)\n", errno, strerror(errno));
			goto error;
		}
		if(time_out == 5)
			lock = 0xFF;
		if(IMX6S_ROT270_FLAG){
			if(((lock >> 5) & 0x03) == 0x03)
				status |= 0x01 << i;
			else{
				if(i == 0){
					logmsg("==========>>>>lock[%d] value is 0x%X\n", i, lock);
				}
			}
		}else{
			if((lock >> 7) == 0)
				status |= 0x01 << i;
		}
	}

	close(fd);
	return status;
error:
	return 0x00;
}

int tp2855_mipi_channel_enable_all(tw2855_context_t* ctx, uint8_t _enable){
	tp28xx_write_reg(ctx, 0x40, MIPI_PAGE); //MIPI page
	if(_enable){
		tp28xx_write_reg(ctx, 0x22, 0x0F);
	}
	else{
		tp28xx_write_reg(ctx, 0x22, 0x00);
	}
	return (0);
}

int tp2855_mipi_channel_enable(tw2855_context_t* ctx,uint8_t channel){
	uint32_t chanl_en_reg = 0;
	if(channel > 3){
		return (EINVAL);
	}
	tp28xx_write_reg(ctx, 0x40, MIPI_PAGE); //MIPI page
	chanl_en_reg = tp28xx_read_reg(ctx, 0x22);
	if(0 == (chanl_en_reg & (1<<channel))){
		chanl_en_reg |=  1<<channel;
		tp28xx_write_reg(ctx, 0x22, chanl_en_reg);
	}
	return 0;
}
